package com.ybg.share.schedule;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ybg.framework.constant.RedisKey;
import com.ybg.framework.core.NetasetSendEmail;
import com.ybg.framework.core.zookeeper.DefaultZkLockConfig;
import com.ybg.framework.core.zookeeper.ZkDistributedLock;
import com.ybg.framework.enums.PbestEnum;
import com.ybg.share.core.dbapi.entity.*;
import com.ybg.share.core.dbapi.service.ShareReceiveEmailService;
import com.ybg.share.core.dbapi.service.ShareStockEvaluateService;
import com.ybg.share.core.dbapi.service.ShareStockPbestService;
import com.ybg.share.core.pbest.vo.PbestEmailVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Slf4j
@Component
public class EmailJob {

    @Autowired
    NetasetSendEmail netasetSendEmail;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    ShareReceiveEmailService shareReceiveEmailService;

    @Autowired
    ShareStockPbestService shareStockPbestService;
    @Autowired
    DefaultZkLockConfig defaultZkLockConfig;
    @Autowired
    ShareStockEvaluateService shareStockEvaluateService;

    static HashMap<Long, ShareStockDayK> shareStockPbestset = new HashMap<Long, ShareStockDayK>(4000);
    static HashMap<Long, ShareFinancialYear> shareStockFinancialSet = new HashMap<>(4000);
    static HashMap<Long,ShareStockEvaluate> shareStockEvaluateSet = new HashMap<>(4000);

    /**
     * 发送推荐股票电子邮件
     */
    @Scheduled(cron = "0 30 7 * * ?")
    public void emialPbest() {
        ZkDistributedLock lock = new ZkDistributedLock(defaultZkLockConfig, "emialPbest");
        boolean trylock = lock.tryLock();
        if (!trylock) {
            return;
        }
        try {
            QueryWrapper<ShareStockPbest> wrapper = new QueryWrapper<>();
            wrapper.eq(ShareStockPbest.PBEST_NAME, PbestEnum.DAY250.name());
            wrapper.eq(ShareStockPbest.REF_YEAR, DateUtil.thisYear());
            List<ShareStockPbest> shareStockPbests = shareStockPbestService.list(wrapper);
            Object[] dayKRedis = (Object[]) redisTemplate.opsForSet().members(RedisKey.LAST_DAY_K).toArray();
            if (dayKRedis.length == 0) {
                return;
            }
            for (Object dayKRedi : dayKRedis) {
                ShareStockDayK shareStockDayK = JSONObject.parseObject(dayKRedi.toString(), ShareStockDayK.class);
                shareStockPbestset.put(shareStockDayK.getStockId(), shareStockDayK);
            }

            QueryWrapper<ShareReceiveEmail> emailWrapper = new QueryWrapper<>();
            emailWrapper.le(ShareReceiveEmail.START_TIME, DateUtil.now());
            emailWrapper.ge(ShareReceiveEmail.END_TIME, DateUtil.now());
            List<ShareReceiveEmail> list = shareReceiveEmailService.list(emailWrapper);
            //存入个股利润Map里面
            for (int i = 0; i < 3; i++) {
                int year = DateUtil.thisYear() - 1 - i;
                Object[] members = redisTemplate.opsForSet().members(RedisKey.SHARE_FINANCIAL_YEAR + year).toArray();
                if (members == null || members.length == 0) {
                    continue;
                }
                for (Object member : members) {
                    ShareFinancialYear shareFinancialYear = JSONObject.parseObject(member.toString(), ShareFinancialYear.class);
                    if (shareStockFinancialSet.get(shareFinancialYear.getStockId()) != null) {
                        //已经有最新的就不用在查了
                        continue;
                    }
                    shareStockFinancialSet.put(shareFinancialYear.getStockId(), shareFinancialYear);
                }
            }
            //
            log.info("shareStockFinancialSet.size="+shareStockFinancialSet.size());
            QueryWrapper<ShareStockEvaluate> shareStockEvaluateWrapper= new QueryWrapper<>();
            shareStockEvaluateWrapper.gt(ShareStockEvaluate.FOCUS,0);
            shareStockEvaluateWrapper.gt(ShareStockEvaluate.TOTAL_SCORE,0);
            shareStockEvaluateWrapper.lt(ShareStockEvaluate.RANKING,9999);
            shareStockEvaluateWrapper.lt(ShareStockEvaluate.TURNOVER_RATE,10);
            shareStockEvaluateWrapper.le(ShareStockEvaluate.PE_RATION,20);
            List<ShareStockEvaluate> stockEvaluates = shareStockEvaluateService.list(shareStockEvaluateWrapper);
            for (ShareStockEvaluate stockEvaluate : stockEvaluates) {
                if(stockEvaluate.getStockId()==null){
                    //可能出现不存在的数据所以跳过
                    continue;
                }
                shareStockEvaluateSet.put(stockEvaluate.getStockId(),stockEvaluate);
            }
            log.info("shareStockEvaluateSet.size="+shareStockEvaluateSet.size());
            //存入个股利润Map里面 结束

            List<PbestEmailVO> contents = new ArrayList<>(dayKRedis.length);
            // System.out.println("shareStockPbestset长度："+shareStockPbestset.size());
            for (ShareStockPbest shareStockPbest : shareStockPbests) {
                ShareStockDayK shareStockDayK = shareStockPbestset.get(shareStockPbest.getStockId());
                if (shareStockDayK == null) {
                    continue;
                }
                PbestEmailVO vo = new PbestEmailVO();
                BeanUtils.copyProperties(shareStockPbest, vo);
                vo.setPrice(shareStockDayK.getClosePrice());
                vo.setOddsRatio(vo.getSellPrice().subtract(vo.getPrice()).divide(vo.getSellPrice().subtract(vo.getBuyPrice()), 2));
                ShareStockEvaluate shareStockEvaluate = shareStockEvaluateSet.get(vo.getStockId());
                if(shareStockEvaluate !=null){
                    vo.setFocus(shareStockEvaluate.getFocus() );
                    vo.setJgcyd(shareStockEvaluate.getJgcyd());
                    vo.setJgcydType(shareStockEvaluate.getJgcydType());
                    vo.setTotalScore(shareStockEvaluate.getTotalScore());
                    vo.setRanking(shareStockEvaluate.getRanking());
                    vo.setPeRation(shareStockEvaluate.getPeRation());
                }else{
                    continue;
                }
                ShareFinancialYear shareFinancialYear = shareStockFinancialSet.get(vo.getStockId());
                if (shareFinancialYear == null) {
                     continue;
                }
                //净利润不够一千万的 直接认为盈利差 不再推荐
                if (shareFinancialYear.getNetProfit().compareTo(new BigDecimal("1000")) < 0) {
                    continue;
                }
                if (vo.getOddsRatio().compareTo(new BigDecimal("0.9")) < 0 || vo.getStockName().contains("ST")) {
                    //排除掉误差比很大的以及退市的股票
                    continue;
                }
                if (vo.getTimes() > 19 && vo.getProfitRate().compareTo(new BigDecimal("0.5")) < 0) {
                    //过滤掉操作次数太多并且利润率太低的股票
                    continue;
                }
                if (vo.getPrice().compareTo(BigDecimal.ONE) < 0) {
                    //价格小于1的 过滤掉
                    continue;
                }
                if (vo.getStockName().contains("B") || vo.getStockName().contains("Ｂ")) {
                    //不推荐B股
                    continue;
                }

                contents.add(vo);
            }

          //  getActiveContent(contents);
            for (ShareReceiveEmail shareReceiveEmail : list) {
                netasetSendEmail.sendMail(shareReceiveEmail.getEmail(), "ybg_share智能推荐股票", getActiveContent(contents,shareReceiveEmail.getEmail()));
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("error{}", e);
        } finally {
            lock.unlock();
        }
        //清空内存
        shareStockPbestset = new HashMap<>(4000);
        shareStockFinancialSet = new HashMap<>(4000);
        shareStockEvaluateSet= new HashMap<>(4000);
    }


    /**
     * 获取拼接的激活邮件的内容
     * <p>
     * 激活链接
     *
     * @param list
     * @return 字符串形的邮件内容
     */
    private String getActiveContent(List<PbestEmailVO> list,String email) {
        StringBuilder buffer = new StringBuilder();
        buffer.append("<html><head>");
        buffer.append("<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">");
        buffer.append("<base target=\"_blank\" />");
        buffer.append("</head>");
        buffer.append("<body>股市有风险，投资需谨慎 推荐内容如下：(·差异比·越接近1 越接近理想值)，·入场次数·越少，则代表这一年是长线，也意味着持有时间长)，·利润率·是所有利润加起来的总和除以本金 <br/>");
        buffer.append("当前版本v1.0.5 </br>");
        buffer.append("算法简要描述（对价格，年度净利润(小于一千万不推荐),市盈率<=20 分析 ） ，换手率小于10% ，热门股 </br>");
        buffer.append("<table><tr><td>股票名称</td><td>股票代码</td><td>买入指导价</td><td>卖出指导价</td><td>当前价</td><td>差异比</td><td>算法利润</td><td>算法利润率</td><td>算法入场次数</td>");
        buffer.append("<td>关注度</td>");
        buffer.append("<td>机构参与度</td>");
        buffer.append("<td>机构参与度描述</td>");
        buffer.append("<td>综合得分</td>");
        buffer.append("<td>综合得分排名</td>");
        buffer.append("</tr>");

        for (PbestEmailVO pbestEmailVO : list) {


            buffer.append("<tr><td>").append(pbestEmailVO.getStockName()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getStockCode()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getBuyPrice()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getSellPrice()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getPrice()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getOddsRatio()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getProfit()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getProfitRate()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getTimes()).append("</td>");

            buffer.append("<td>").append(pbestEmailVO.getFocus()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getJgcyd()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getJgcydType()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getTotalScore()).append("</td>");
            buffer.append("<td>").append(pbestEmailVO.getRanking()).append("</td>");

            buffer.append("</tr>");
        }


        buffer.append("</table><br>");
        buffer.append("<a href='http://www.88ybg.com:8090/ybg_share/api/download/download?email="+email+"'>下载全部数据</a>");
        buffer.append("</body>");
        buffer.append("</html>");
        // System.out.println(buffer.toString());
        return buffer.toString();
    }


}
